#pragma once

class Actor;
class CameraStrategy;

class Camera : public Actor
{
public:
	Camera(void);
	~Camera(void);

	/**
	@param	x,y,z direction, w force scaler, must be normalized, it will be used to multiple the speed of camera
	@remark 
	*/
	void moveLocal(const vec3f& dir);
	void pitch(float angle);
	void yaw(float angle);
	void roll(float angle);
	void setPosition(const vec3f& pos);

	void update(float dt);

	/**
	@param halfAngleInDegree half angle of field of view, in degree
	@param ratio width : height
	@param znear near z
	@param zfar far z
	@remark z is point into the screen, this function calculate projection matrix only, will not send it to render.
	*/
	void setPerspective(float halfAngleInDegree, float ratio, float znear, float zfar);
	
	/**
	@param	strategy strategy of user defined, if set to null, it will use default strategy which will do nothing in update
	@remark 
	*/
	void setCameraStrategy(CameraStrategy* strategy) { cameraStrategyCurrent = strategy; strategy->initializeCamera(this); }
	
	// getters
	const mat4f& getProjectionMatrix() const { return matProjection; }
	const mat4f& getViewMatrix() const { return matView; }

private:
	mat4f matProjection;
	mat4f matView;
	float cameraSpeed;
	bool bDirty;
	float cameraXRotSpeed;
	float cameraYRotSpeed;

	CameraStrategy* cameraStrategyCurrent;
};